package cn.yuysaln.domain.strategy.service;

import cn.yuysaln.domain.strategy.model.entity.*;
import cn.yuysaln.domain.strategy.model.valobj.RuleLogicCheckTypeVO;
import cn.yuysaln.domain.strategy.model.valobj.StrategyAwardRuleModelVO;
import cn.yuysaln.domain.strategy.repository.IStrategyRepository;
import cn.yuysaln.domain.strategy.service.IRaffleStrategy;
import cn.yuysaln.domain.strategy.service.armory.IStrategyDispatch;
import cn.yuysaln.domain.strategy.service.rule.chain.ILogicChain;
import cn.yuysaln.domain.strategy.service.rule.chain.factory.DefaultChainFactory;
import cn.yuysaln.domain.strategy.service.rule.filter.factory.DefaultLogicFactory;
import cn.yuysaln.types.enums.ResponseCode;
import cn.yuysaln.types.exception.AppException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import cn.yuysaln.domain.strategy.service.rule.tree.factory.DefaultTreeFactory;

import java.util.Date;

/**
 * 抽奖流程模板类
 */
@Slf4j
public abstract class AbstractRaffleStrategy implements IRaffleStrategy {
    protected IStrategyRepository repository;    // 数据repo接口
    protected IStrategyDispatch strategyDispatch;   //派奖接口
    protected final DefaultChainFactory defaultChainFactory;  // 责任链工厂
    protected final DefaultTreeFactory defaultTreeFactory;  //规则树工厂

    //依赖注入
    public AbstractRaffleStrategy(IStrategyRepository repository, IStrategyDispatch strategyDispatch, DefaultChainFactory defaultChainFactory, DefaultTreeFactory defaultTreeFactory) {
        this.repository = repository;
        this.strategyDispatch = strategyDispatch;
        this.defaultChainFactory = defaultChainFactory;
        this.defaultTreeFactory = defaultTreeFactory;
    }

    /**
     * 传入抽奖因子（用户Id，策略Id）  开始抽奖
     * @param raffleFactorEntity 抽奖因子实体对象，根据入参信息计算抽奖结果
     * @return 奖品Entity
     */
    @Override
    public RaffleAwardEntity performRaffle(RaffleFactorEntity raffleFactorEntity){
        //校验参数
        String userId = raffleFactorEntity.getUserId();
        Long strategyId = raffleFactorEntity.getStrategyId();
        if (null == strategyId || StringUtils.isBlank(userId)){
            throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(),ResponseCode.ILLEGAL_PARAMETER.getInfo());
        }

        //责任链前置过滤
        DefaultChainFactory.StrategyAwardVO chainStrategyAwardVO = raffleLogicChain(userId, strategyId);
        log.info("抽奖策略计算-责任链过滤完成 {} {} {} {}", userId, strategyId, chainStrategyAwardVO.getAwardId(), chainStrategyAwardVO.getLogicModel());
        //黑名单直接返回，权重肯定中奖  所以非默认规则直接都返回
        if (!DefaultChainFactory.LogicModel.RULE_DEFAULT.getCode().equals(chainStrategyAwardVO.getLogicModel())){
            return buildRaffleAwardEntity(strategyId,chainStrategyAwardVO.getAwardId(),null);

        }

        //默认下先得到一个初步奖品，再使用规则树进行中后段的过滤
        DefaultTreeFactory.StrategyAwardVO treeStrategyAwardVO = raffleLogicTree(userId, strategyId,chainStrategyAwardVO.getAwardId(),raffleFactorEntity.getEndDateTime());
        log.info("抽奖策略计算-规则树过滤完成 {} {} {} {}", userId, strategyId, treeStrategyAwardVO.getAwardId(), treeStrategyAwardVO.getAwardRuleValue());

        //全部过滤走完，返回结果
        return buildRaffleAwardEntity(strategyId,treeStrategyAwardVO.getAwardId(),treeStrategyAwardVO.getAwardRuleValue());

    }

    /**
     * 辅助函数，用于创建抽奖奖品实体
     * @param strategyId
     * @param awardId
     * @param awardConfig
     * @return
     */
    private RaffleAwardEntity buildRaffleAwardEntity(Long strategyId,Integer awardId,String awardConfig){
        StrategyAwardEntity strategyAwardEntity =  repository.queryStrategyAwardEntity(strategyId,awardId);
        return RaffleAwardEntity.builder()
                .awardId(awardId)
                .awardTitle(strategyAwardEntity.getAwardTitle())
                .awardConfig(awardConfig)
                .sort(strategyAwardEntity.getSort())
                .build();
    }

    /**
     * 责任链模式处理抽奖前置过滤
     * @param userId 用户ID
     * @param strategyId 策略ID
     * @return 奖品VO对象
     */
    public abstract DefaultChainFactory.StrategyAwardVO raffleLogicChain(String userId,Long strategyId);

    /**
     * 规则树处理抽奖中、后过滤
     * @param userId 用户ID
     * @param strategyId 策略ID
     * @param awardId 奖品ID
     * @return 奖品VO对象
     */
    public abstract DefaultTreeFactory.StrategyAwardVO raffleLogicTree(String userId,Long strategyId, Integer awardId);
    public abstract DefaultTreeFactory.StrategyAwardVO raffleLogicTree(String userId, Long strategyId, Integer awardId, Date endDateTime);




    //以下代码被优化
    protected abstract RuleActionEntity<RuleActionEntity.RaffleBeforeEntity> doCheckRaffleBeforeLogic(RaffleFactorEntity raffleFactorEntity,String... logics);
    protected abstract RuleActionEntity<RuleActionEntity.RaffleCenterEntity> doCheckRaffleCenterLogic(RaffleFactorEntity raffleFactorEntity,String... logics);
}
